/*
        这份代码是关于：线程等待、线程终止

        int pthread_join(pthread_t thread, void **retval);
        1、第一个参数是要等待线程的tid。
        2、第二个参数：返回给主线程的结果。

        一个新线程创建出来是主线程先执行还是新线程先执行是不确定的，因为在Linux系统中，线程就是轻量级进程。
        但是主线程应该是最后退出的。因为主线程是创建新线程的。创建它就要管理它。
        新线程创建也要被主线程等待，如果主线程不等待。也会造成类似僵尸进程那样的问题。
        线程等待两目的：1、防止新线程造成内存泄漏  2、如果需要，也可以获取新线程的退出结果。

        新线程执行完，是通过函数返回值来告诉我们的。主线程如何得到新线程的返回结果呢？ pthread_join函数中的第二个参数。

        线程终止：1、return   2、exit(终止进程的，不能终止线程)  3、pthread_exit()  4、pthread_cancel(取消一个线程)

        如果一个线程是被取消的，该线程对应的退出结果是PTHREAD_CANCELED(-1)
*/

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <string>

using namespace std;

int g_val = 100;

void show(const string& name)
{
    cout << name << "say# " << "hello thread" << endl;
}

void* threadRoutine(void* args)
{
    int cnt = 5;
    while(true)
    {
        printf("new thread pid: %d, g_val: %d, &g_val: 0x%p, cnt: %d\n", getpid(), g_val, &g_val, cnt);
        // cout << "new thread, pid: " << getpid() << ", g_val: " << g_val << endl;
        // show("[new thread]");
        sleep(1);
        // g_val++;
        cnt--;
        if(cnt == 0) break;
    }

    pthread_exit((void*)100);
    // exit(11); // exit是用来终止进程的，不能用来终止线程。
    // return nullptr;  // 走到这里默认线程退出了！
    // return (void*)11;  // 11当做一个地址会拷贝到void*变量中。
}

int main()
{
    pthread_t pid;
    pthread_create(&pid, nullptr, threadRoutine, nullptr); 

    sleep(1); // 保证新线程已经启动

    pthread_cancel(pid);  // 取消一个新线程
    // while(true)
    // {
    //     printf("main thread pid: %d, g_val: %d, &g_val: 0x%p\n", getpid(), g_val, &g_val);
    //     // cout << "main thread, pid: " << getpid() << ", g_val: " << g_val << endl;
    //     // show("[main thread]");
    //     sleep(1);
    //     g_val++;
    // }

    // PTHREAD_CANCELED;
    void* ret = nullptr;
    printf("main thread running .................\n");
    pthread_join(pid, &ret); // 主线程等待的时候，默认是阻塞等待的。
    // printf("main thread quit! ................., ret: %p\n", (int)ret);  // 指针8字节，强转会报错，应该转为long long
    cout << "main thread quit! .........., ret: " << (long long int)ret << endl;
    return 0;
}